﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Zatify.Domain.Abstract;
using Zatify.Domain.Data;
using Zatify.Domain.Entities;

namespace Zatify.Domain.Concrete
{
    public class ZatifyRepository : IZatifyRepository
    {
        private ZatifyEntities ZatifyEFDB = new ZatifyEntities();

        public spAPI_User_Login_Result LoginUser(string loginName, string password)
        {
            return this.ZatifyEFDB.spAPI_User_Login(loginName, password).First();
        }

        #region Users

        public IQueryable<User> Users
        {
            get { return ZatifyEFDB.User_GetList().AsQueryable(); }
        }

        public User GetUserById(int id)
        {
            return ZatifyEFDB.User_GetById(id).FirstOrDefault();
        }

        public void UpdateUser(User user)
        {
            ZatifyEFDB.User_Update(user.Id, user.Email, user.Phone, user.IsActive, user.RegState, user.RegCity);
        }

        public void AddUser(User user)
        {
            ZatifyEFDB.User_AddUser(user.Login, user.Email, user.Phone, user.Password);
        }

        public void UserChangePassword(int userId, string newPassword)
        {
            ZatifyEFDB.User_ChangePassword(userId, newPassword);
        }

        public void UserDeleteById(int id)
        {
            ZatifyEFDB.User_DeleteById(id);
        }

        public void UsersDeleteByIds(int[] userIds)
        {
            var stringUsersIds = String.Join(",", userIds.Select(id => id.ToString()));

            ZatifyEFDB.User_DeleteSelected(stringUsersIds);
        }

        public void UserChangeStatus(int userId, bool isActive)
        {
            ZatifyEFDB.User_ChangeStatus(userId, isActive);
        }

        public void UsersChangeStatus(int[] userIds, bool isActive)
        {
            var stringUsersIds = String.Join(",", userIds.Select(id => id.ToString()));

            if (isActive)
                ZatifyEFDB.User_ActivateSelected(stringUsersIds);
            else
                ZatifyEFDB.User_DeactivateSelected(stringUsersIds);
        }

        public User_Register_Result UserRegister(User user)
        {
            user.Email = user.Email ?? String.Empty;
            user.Phone = user.Phone ?? String.Empty;
            user.ZipCode = user.ZipCode ?? String.Empty;
            user.ReferredBy = user.ReferredBy ?? String.Empty;
            user.RegState = user.RegState ?? String.Empty;
            user.RegCity = user.RegCity ?? String.Empty;
            user.PhotoContentType = user.PhotoContentType ?? String.Empty;

            return ZatifyEFDB.User_Register(user.Login, user.Password, user.Email, user.Phone, user.ZipCode, user.ReferredBy, user.PhotoContentType, user.Photo).First();
        }

        public User UserGetByToken(Guid token)
        {
            var user = ZatifyEFDB.User_GetProfileByToken(token.ToString(), true).First();
            user.SecurityToken = token;
            user.UserRole = UserRole.RegularUser;

            return user;
        }

        public Int32 UserUpdateByToken(Guid token, User user)
        {
            return this.ZatifyEFDB.spAPI_User_UpdateProfile(token.ToString(),
                            user.Password, user.Email, user.Phone, user.PhotoContentType, user.Photo, user.ZipCode).First().Value;
        }

        public User BusinessUserGetByToken(Guid token)
        {
            var business = ZatifyEFDB.spAPI_Business_GetProfile(token.ToString(), true, null).First();

            return new User()
            {
                SecurityToken = token,
                Login = business.Login,
                UserRole = UserRole.BusinessUser
            };
        }

        public Int32 UserAddCategories(Guid token, string categoriesIds)
        {
            return UserUpdateCategories(token, categoriesIds);
        }

        public Int32 UserUpdateCategories(Guid token, string categoriesIds)
        {
            return this.ZatifyEFDB.User_UpdateCategory(token.ToString(), categoriesIds).First().Value;
        }

        public List<Category> UserGetCategories(Guid token)
        {
            return this.ZatifyEFDB.spAPI_UserCategory_GetList(token.ToString(), true).ToList();
        }


        public Int32 UserFavoriteBusinessesAdd(Guid token, string businessIds)
        {
            return this.ZatifyEFDB.spAPI_UserFavorites_Add(token.ToString(), businessIds).First().Value;
        }

        public Int32 UserFavoriteBusinessesDelete(Guid token, string businessIds)
        {
            return this.ZatifyEFDB.spAPI_UserFavorites_Delete(token.ToString(), businessIds).First().Value;
        }

        public Int32 UserBlockBusinesses(Guid token, string businessIds)
        {
            return this.ZatifyEFDB.spAPI_BlockBusiness_Update(token.ToString(), businessIds).First().Value;
        }

        public Int32 UserBlockCategories(Guid token, string categoryIds)
        {
            return this.ZatifyEFDB.spAPI_BlockCategory_Update(token.ToString(), categoryIds).First().Value;
        }

        public Int32 UserBlockPromotions(Guid token, string promotionIds)
        {
            return this.ZatifyEFDB.spAPI_BlockPromotion_Update(token.ToString(), promotionIds).First().Value;
        }
        
        #endregion

        #region UserSettings

        public UserSettings UserSettingsGetByToken(Guid token)
        {
            return this.ZatifyEFDB.spAPI_UserSetting_GetList(token.ToString(), true).First();
        }

        public Int32 UserSettingsUpdateByToken(Guid token, string settings, string value)
        {
            return this.ZatifyEFDB.spAPI_UserSetting_Update(token.ToString(), settings, value).First().Value;
        }

        #endregion

        #region SystemUsers

        public IQueryable<SystemUser> SystemUsers
        {
            get { return ZatifyEFDB.SystemUser_GetList().AsQueryable(); }
        }

        public void SystemUserAdd(SystemUser user)
        {
            ZatifyEFDB.SystemUser_Add(user.Login, user.Email, user.Phone, user.Password, user.Role);
        }

        public void SystemUserUpdate(SystemUser user)
        {
            ZatifyEFDB.SystemUser_Update(user.SystemUserId, user.Email, user.Phone, user.Role, user.IsActive);
        }

        public void SystemUserChangePassword(int userId, string newPassword)
        {
            ZatifyEFDB.SystemUser_ChangePassword(userId, newPassword);
        }

        public void SystemUserDeleteById(int id)
        {
            ZatifyEFDB.SystemUser_Delete(id);
        }

        public void SystemUsersDeleteByIds(int[] userIds)
        {
            var stringUsersIds = String.Join(",", userIds.Select(id => id.ToString()));

            ZatifyEFDB.SystemUser_DeleteSelected(stringUsersIds);
        }

        public void SystemUserChangeStatus(int userId, bool isActive)
        {
            ZatifyEFDB.SystemUser_ChangeStatus(userId, isActive);
        }

        public void SystemUsersChangeStatus(int[] userIds, bool isActive)
        {
            var stringUsersIds = String.Join(",", userIds.Select(id => id.ToString()));

            if (isActive)
                ZatifyEFDB.SystemUser_ActivateSelected(stringUsersIds);
            else
                ZatifyEFDB.SystemUser_DeactivateSelected(stringUsersIds);
        }

        #endregion

        #region Rates

        public IQueryable<BaseCostTiming> BaseCostTimings
        {
            get { return ZatifyEFDB.BaseCostTiming_GetList().AsQueryable(); }
        }

        public void BaseCostTimingsUpdate(ICollection<BaseCostTiming> baseCostTimings)
        {
            foreach (var baseCostTiming in baseCostTimings)
            {
                ZatifyEFDB.BaseCostTiming_Update(
                    baseCostTiming.BaseCostTimingId,
                    baseCostTiming.Timing,
                    baseCostTiming.RatePerPush,
                    baseCostTiming.FixedCost);
            }
        }

        public ProximityRadius ProximityRadiusGetById(int id)
        {
            return ZatifyEFDB.ProximityRadius_GetById(id).FirstOrDefault();
        }

        public IQueryable<ProximityRadius> ProximityRadiuses
        {
            get { return ZatifyEFDB.ProximityRadius_GetList().AsQueryable(); }
        }

        public void ProximityRadiusesUpdate(ICollection<ProximityRadius> proximityRadiuses)
        {
            foreach (var proximityRadius in proximityRadiuses)
            {
                ZatifyEFDB.ProximityRadius_Update(
                    proximityRadius.ProximityRadiusId,
                    proximityRadius.FromRadius,
                    proximityRadius.ToRadius,
                    proximityRadius.RatePerPush,
                    proximityRadius.FixedCost,
                    proximityRadius.IsCustomRate
                    );
            }
        }


        public IQueryable<ProximityRadiusOutside> ProximityRadiusesOutside
        {
            get { return ZatifyEFDB.ProximityRadiusOutside_GetList().AsQueryable(); }
        }

        public void ProximityRadiusesOutsideUpdate(ICollection<ProximityRadiusOutside> proximityRadiusesOutside)
        {
            foreach (var proximityRadiusOutside in proximityRadiusesOutside)
            {
                ZatifyEFDB.ProximityRadiusOutside_Update(
                    proximityRadiusOutside.ProximityRadiusOutsideCode,
                    proximityRadiusOutside.RatePerPush,
                    proximityRadiusOutside.FixedCost);
            }
        }


        #endregion

        #region Defaults

        public IQueryable<SystemDefault> SystemDefaults
        {
            get { return ZatifyEFDB.SystemDefault_GetList().AsQueryable(); }
        }

        public void SystemDefaultUpdate(string parameterCode, string value)
        {
            ZatifyEFDB.SystemDefault_Update(parameterCode, value);
        }

        public TimeSpan SystemDefaultsGetBusinessHourFrom()
        {
            var businessHourFrom = TimeSpan.Parse(ZatifyEFDB.SystemDefault_GetList().FirstOrDefault(sd => sd.ParameterCode == "BUSINESS_HOURS_FROM").Value);

            return businessHourFrom;
        }

        public TimeSpan SystemDefaultsGetBusinessHourTo()
        {
            var businessHourTo = TimeSpan.Parse(ZatifyEFDB.SystemDefault_GetList().FirstOrDefault(sd => sd.ParameterCode == "BUSINESS_HOURS_TO").Value);

            return businessHourTo;
        }

        #endregion

        #region Categories

        public IQueryable<Category> Categories
        {
            get { return ZatifyEFDB.Category_GetList().AsQueryable(); }
        }

        public void CategoriesAdd(Category category)
        {
            ZatifyEFDB.spCategory_Add(category.CategoryName, category.ParentId, category.IsSingularSelection.Value, category.IsRoot.Value, category.SortOrder, category.CategoryDescription, category.NotMergeable);
        }

        public void CategoriesUpdate(Category category)
        {
            this.ZatifyEFDB.spCategory_Update(category.CategoryId, category.CategoryName, category.ParentId, category.IsSingularSelection, category.IsRoot, category.SortOrder, category.CategoryDescription, category.NotMergeable);
        }

        public void CategoriesDelete(int id)
        {
            ZatifyEFDB.Category_Delete(id);
        }

        public void CategoriesDeleteSelected(string ids)
        {
            //var stringCategoriesIds = String.Join(",", ids.Select(id => id.ToString()));
            ZatifyEFDB.Category_DeleteSelected(ids);
        }

        public IQueryable<Category> CategoriesGetAll()
        {
            return ZatifyEFDB.Categories_GetAll(true).AsQueryable();
        }

        public void CategoryMove(int categoryId, int? parentCategoryId)
        {
            this.ZatifyEFDB.spAPI_MoveCategory(categoryId, parentCategoryId);
        }

        #endregion

        #region CategoriesRequest

        public IQueryable<CategoryRequest> CategoryRequests
        {
            get { return ZatifyEFDB.CategoryRequest_GetList().AsQueryable(); }
        }

        public void CategoryRequestDelete(int[] categoryRequestIds)
        {
            var strIds = String.Join(",", categoryRequestIds.Select(id => id.ToString()));
            ZatifyEFDB.CategoryRequest_Delete(strIds);
        }

        public void CategoryRequestConfirm(int categoryRequestId, int? parentCategoryId)
        {
            ZatifyEFDB.CategoryRequest_Confirm(categoryRequestId, parentCategoryId);
        }

        #endregion

        #region Messages

        public IQueryable<Message> MessagesGetInboxMessages(string loginName)
        {
            return ZatifyEFDB.MessageCenter_SystemUser_GetInbox(loginName).AsQueryable();
        }

        public IQueryable<Message> MessagesGetOutboxMessages(string loginName)
        {
            return ZatifyEFDB.MessageCenter_SystemUser_GetOutbox(loginName).AsQueryable();
        }

        public Message MessagesGetById(int messageId)
        {
            return ZatifyEFDB.MessageCenter_SystemUser_GetMessageById(messageId).FirstOrDefault();
        }

        public void MessagesAdd(Message message)
        {
            ZatifyEFDB.MessageCenter_SystemUser_Add(message.Subject, message.Body, message.FromSystemLogin, message.ToUserLogin);
        }

        public void MessagesAddToAllUsers(Message message)
        {
            ZatifyEFDB.MessageCenter_SystemUser_Add_All(message.Subject, message.Body, message.FromSystemLogin);
        }
        public void MessagesAddToBusinessUsers(Message message)
        {
            ZatifyEFDB.MessageCenter_SystemUser_Add_All_Business(message.Subject, message.Body, message.FromSystemLogin);
        }
        public void MessagesAddToEndUsers(Message message)
        {
            ZatifyEFDB.MessageCenter_SystemUser_Add_All_User(message.Subject, message.Body, message.FromSystemLogin);
        }

        public void MessagesSetStatus(int messageId, string status)
        {
            ZatifyEFDB.MessageCenter_SetStatus(messageId, status);
        }

        public void MessagesDeleteInboxById(int messageId)
        {
            ZatifyEFDB.MessageCenter_DeleteInbox(messageId);
        }
        public void MessagesDeleteOutboxById(int messageId)
        {
            ZatifyEFDB.MessageCenter_DeleteOutbox(messageId);
        }

        #endregion

        #region Business

        public IQueryable<Business> Businesses { get { return ZatifyEFDB.Business_GetList().AsQueryable(); } }

        public Business BusinessGetById(int id)
        {
            return ZatifyEFDB.Business_GetById(id).FirstOrDefault();
        }

        public Business BusinessGetByToken(Guid token)
        {
            return ZatifyEFDB.spAPI_Business_GetProfile(token.ToString(), true, null).First();
        }

        public void BusinessUpdate(Business business, BusinessHours businessHours, List<Category> categories)
        {
            ZatifyEFDB.Business_Update(business.BusinessId, business.Login, business.Email, business.Password, business.BusinessName, business.Web,
             business.BusinessPhone, business.CellPhone, business.TollFreePhone, business.Fax, business.StreetAddress1, business.StreetAddress2,
             business.City, business.StateCode, business.ZipCode, business.Description, business.CreditCardNo, business.CreditCardExpDate,
             business.CreditCardName, business.CreditCardPin, business.BillingAddress1, business.BillingAddress2, business.BillingCity,
             business.BillingStateCode, business.BillingZipCode, business.BillingUse,
             DateTime.Parse(businessHours.SunFrom.ToString()), DateTime.Parse(businessHours.SunTo.ToString()), businessHours.SunClosed,
             DateTime.Parse(businessHours.MonFrom.ToString()), DateTime.Parse(businessHours.MonTo.ToString()), businessHours.MonClosed,
             DateTime.Parse(businessHours.TueFrom.ToString()), DateTime.Parse(businessHours.TueTo.ToString()), businessHours.TueClosed,
             DateTime.Parse(businessHours.WedFrom.ToString()), DateTime.Parse(businessHours.WedTo.ToString()), businessHours.WedClosed,
             DateTime.Parse(businessHours.ThuFrom.ToString()), DateTime.Parse(businessHours.ThuTo.ToString()), businessHours.ThuClosed,
             DateTime.Parse(businessHours.FriFrom.ToString()), DateTime.Parse(businessHours.FriTo.ToString()), businessHours.FriClosed,
             DateTime.Parse(businessHours.SatFrom.ToString()), DateTime.Parse(businessHours.SatTo.ToString()), businessHours.SatClosed,
             GetCategoriesIDsAsString(categories),
             business.Picture, business.PictureContentType,
             business.Latitude, business.Longitude);
        }

        public Int32 BusinessUpdate(Guid token, Business business, BusinessHours businessHours, string categoriesIds, string categoryNewName1, string categoryNewName2, string categoryNewName3,
            double? latitude, double? longitude, int? gmt)
        {
            return this.ZatifyEFDB.spAPI_Business_Update(token.ToString(),
                business.Password, business.Email, business.BusinessName, business.Web, business.BusinessPhone, business.CellPhone, business.TollFreePhone, business.Fax,
                business.StreetAddress1, business.StreetAddress2, business.City, business.StateCode, business.ZipCode, business.Description, business.ReferencedBy,
                DateTime.Parse(businessHours.SunFrom.ToString()), DateTime.Parse(businessHours.SunTo.ToString()), businessHours.SunClosed,
                DateTime.Parse(businessHours.MonFrom.ToString()), DateTime.Parse(businessHours.MonTo.ToString()), businessHours.MonClosed,
                DateTime.Parse(businessHours.TueFrom.ToString()), DateTime.Parse(businessHours.TueTo.ToString()), businessHours.TueClosed,
                DateTime.Parse(businessHours.WedFrom.ToString()), DateTime.Parse(businessHours.WedTo.ToString()), businessHours.WedClosed,
                DateTime.Parse(businessHours.ThuFrom.ToString()), DateTime.Parse(businessHours.ThuTo.ToString()), businessHours.ThuClosed,
                DateTime.Parse(businessHours.FriFrom.ToString()), DateTime.Parse(businessHours.FriTo.ToString()), businessHours.FriClosed,
                DateTime.Parse(businessHours.SatFrom.ToString()), DateTime.Parse(businessHours.SatTo.ToString()), businessHours.SatClosed,
                categoriesIds, categoryNewName1, categoryNewName2, categoryNewName3,
                latitude, longitude, gmt,
                business.CreditCardNo, business.CreditCardExpDate, business.CreditCardName, business.CreditCardPin, business.BillingUse, business.BillingAddress1, business.BillingAddress2,
                business.BillingCity, business.BillingStateCode, business.BillingZipCode,

                business.PictureContentType,
                business.Picture).FirstOrDefault().Value;
        }

        public void BusinessAdd(Business business)
        {

        }

        public void BusinessDeleteById(int businessId)
        {
            ZatifyEFDB.Business_Delete(businessId);
        }

        public void BusinessesDeleteByIds(int[] ids)
        {
            var stringBusinessesIds = String.Join(",", ids.Select(id => id.ToString()));

            ZatifyEFDB.Business_DeleteSelected(stringBusinessesIds);
        }

        public void BusinessDeleteCategories(int businessId, string categoriesIds)
        {
            ZatifyEFDB.Business_DeleteCategories(businessId, categoriesIds);
        }

        public void BusinessChangePassword(int businessId, string newPassword)
        {
            ZatifyEFDB.Business_ChangePassword(businessId, newPassword);
        }

        public void BusinessChangeStatus(int businessId, bool isActive)
        {
            ZatifyEFDB.Business_ChangeStatus(businessId, isActive);
        }

        public void BusinessesChangeStatus(int[] businessesIds, bool isActive)
        {
            var stringUsersIds = String.Join(",", businessesIds.Select(id => id.ToString()));

            if (isActive)
                ZatifyEFDB.Business_ActivateSelected(stringUsersIds);
            else
                ZatifyEFDB.Business_DeactivateSelected(stringUsersIds);
        }

        public BusinessHours BusinessGetBusinessHours(int businessId)
        {
            var businessHoursData = ZatifyEFDB.Business_GetHours(businessId).ToList();

            if (businessHoursData.Count > 0)
            {
                return new BusinessHours()
                {
                    IsBusinessHoursSpecified = true,

                    SunFrom = businessHoursData.FirstOrDefault(h => h.WeekDay == "Sun").FromTime.TimeOfDay,
                    SunTo = businessHoursData.FirstOrDefault(h => h.WeekDay == "Sun").ToTime.TimeOfDay,
                    SunClosed = businessHoursData.FirstOrDefault(h => h.WeekDay == "Sun").Closed,
                    SunIs24Open = businessHoursData.FirstOrDefault(h => h.WeekDay == "Sun").Is24Open,

                    MonFrom = businessHoursData.FirstOrDefault(h => h.WeekDay == "Mon").FromTime.TimeOfDay,
                    MonTo = businessHoursData.FirstOrDefault(h => h.WeekDay == "Mon").ToTime.TimeOfDay,
                    MonClosed = businessHoursData.FirstOrDefault(h => h.WeekDay == "Mon").Closed,
                    MonIs24Open = businessHoursData.FirstOrDefault(h => h.WeekDay == "Mon").Is24Open,

                    TueFrom = businessHoursData.FirstOrDefault(h => h.WeekDay == "Tue").FromTime.TimeOfDay,
                    TueTo = businessHoursData.FirstOrDefault(h => h.WeekDay == "Tue").ToTime.TimeOfDay,
                    TueClosed = businessHoursData.FirstOrDefault(h => h.WeekDay == "Tue").Closed,
                    TueIs24Open = businessHoursData.FirstOrDefault(h => h.WeekDay == "Tue").Is24Open,

                    WedFrom = businessHoursData.FirstOrDefault(h => h.WeekDay == "Wed").FromTime.TimeOfDay,
                    WedTo = businessHoursData.FirstOrDefault(h => h.WeekDay == "Wed").ToTime.TimeOfDay,
                    WedClosed = businessHoursData.FirstOrDefault(h => h.WeekDay == "Wed").Closed,
                    WedIs24Open = businessHoursData.FirstOrDefault(h => h.WeekDay == "Wed").Is24Open,

                    ThuFrom = businessHoursData.FirstOrDefault(h => h.WeekDay == "Thu").FromTime.TimeOfDay,
                    ThuTo = businessHoursData.FirstOrDefault(h => h.WeekDay == "Thu").ToTime.TimeOfDay,
                    ThuClosed = businessHoursData.FirstOrDefault(h => h.WeekDay == "Thu").Closed,
                    ThuIs24Open = businessHoursData.FirstOrDefault(h => h.WeekDay == "Thu").Is24Open,

                    FriFrom = businessHoursData.FirstOrDefault(h => h.WeekDay == "Fri").FromTime.TimeOfDay,
                    FriTo = businessHoursData.FirstOrDefault(h => h.WeekDay == "Fri").ToTime.TimeOfDay,
                    FriClosed = businessHoursData.FirstOrDefault(h => h.WeekDay == "Fri").Closed,
                    FriIs24Open = businessHoursData.FirstOrDefault(h => h.WeekDay == "Fri").Is24Open,

                    SatFrom = businessHoursData.FirstOrDefault(h => h.WeekDay == "Sat").FromTime.TimeOfDay,
                    SatTo = businessHoursData.FirstOrDefault(h => h.WeekDay == "Sat").ToTime.TimeOfDay,
                    SatClosed = businessHoursData.FirstOrDefault(h => h.WeekDay == "Sat").Closed,
                    SatIs24Open = businessHoursData.FirstOrDefault(h => h.WeekDay == "Sat").Is24Open,
                };
            }
            else
            {
                return new BusinessHours() { IsBusinessHoursSpecified = false };
            }
        }

        public BusinessHoursToday BusinessGetBusinessHoursToday(int businessId)
        {
            return ZatifyEFDB.spBusiness_GetHoursToday(businessId).First();
        }

        public IQueryable<Category> BusinessGetCategories(int businessId)
        {
            return ZatifyEFDB.Business_GetCategories(businessId).AsQueryable();
        }

        private string GetCategoriesIDsAsString(List<Category> categories)
        {
            var categoriesIDs = (from c in categories
                                 select c.CategoryId).ToArray();

            return String.Join(",", categoriesIDs);
        }

        public IQueryable<BusinessBilling> BusinessGetBilling(int businessId, DateTime? dateOperation)
        {
            return ZatifyEFDB.Business_GetBilling(businessId, dateOperation).AsQueryable();
        }

        public bool BusinessIsBusinessLoginFree(string login)
        {
            return ZatifyEFDB.Business_IsBusinessLoginFree(login).FirstOrDefault().Value;
        }


        public IQueryable<Business> BusinessesSearch(Guid token, string search, double? latitude, double? longitude)
        {
            return this.ZatifyEFDB.spAPI_Business_Nearby(token.ToString(), latitude, longitude, true, search).AsQueryable();
        }

        public IQueryable<Business> BusinessesGetUserNearby(Guid token, string zipCode)
        {
            return this.ZatifyEFDB.spAPI_Business_Nearby_GetByZip(token.ToString(), zipCode, String.Empty).AsQueryable();
        }

        public IQueryable<Business> BusinessesGetUserFavorites(Guid token, double? latitude, double? longitude)
        {
            return this.ZatifyEFDB.spAPI_UserFavorites_GetList(token.ToString(), latitude, longitude, true).AsQueryable();
        }

        public IQueryable<BusinessReview> BusinessGetReviews(Guid token, int businessId)
        {
            return this.ZatifyEFDB.spAPI_BusinessReview_GetList(token.ToString(), businessId, true).AsQueryable();
        }

        public Int32 BusinessReviewAdd(Guid token, int businessId, string reviewText, int rating)
        {
            return this.ZatifyEFDB.spAPI_BusinessReview_Add(token.ToString(), businessId, reviewText, rating).First().Value;
        }

        public bool Business_IsBusiness24Open(int id)
        {
            var isBusiness24Open = this.ZatifyEFDB.spIsBusinessOpened24_7(id).FirstOrDefault();

            if (isBusiness24Open != null && isBusiness24Open.HasValue)
                return (isBusiness24Open.Value == 1);
            else
                return false;
        }

        public IQueryable<Promotion> BusinessGetAllActivePromotions(Guid token, int businessId, double? latitude, double? longitude)
        {
            return this.ZatifyEFDB.spAPI_User_GetAllActivePromotionsByBusiness(token.ToString(), businessId, latitude, longitude, true).AsQueryable();
        }

        #endregion

        #region BusinessUser

        public bool BusinessUser_CheckLoginEmail(string login, string email)
        {
            return this.ZatifyEFDB.spBusinessUser_CheckLoginEmail(login, email).First().Value;
        }

        public BusinessRegistrationResult Business_RegisterStep1(string login, string password, string email, string businessName, string web, string businessPhone, string cellPhone,
            string tollFreePhone, string fax, string streetAddress, string streetAddress2, string city, string state, string zip, double? longitude, double? latitude, int? gmt)
        {
            return this.ZatifyEFDB.spAPI_Business_RegisterStep1(login, password, email, businessName, web, businessPhone, cellPhone, tollFreePhone ?? String.Empty,
                fax ?? String.Empty, streetAddress, streetAddress2 ?? String.Empty, city, state, zip, latitude, longitude, gmt ?? 0).FirstOrDefault();
        }

        public Int32 Business_RegisterStep1Update(Guid token, string password, string email, string businessName, string web, string businessPhone, string cellPhone,
            string tollFreePhone, string fax, string streetAddress, string streetAddress2, string city, string state, string zip, double? longitude, double? latitude, int? gmt)
        {
            return this.ZatifyEFDB.spAPI_Business_RegisterStep1Update(token.ToString(), password, email, businessName, web, businessPhone, cellPhone, tollFreePhone ?? String.Empty,
                fax ?? String.Empty, streetAddress, streetAddress2 ?? String.Empty, city, state, zip, latitude, longitude, gmt ?? 0).FirstOrDefault().Value;
        }

        public Int32 Business_RegisterStep2(Guid token, string description, string referencedBy, BusinessHours businessHours,
            string categoriesIds, string newCategoryName1, string newCategoryName2, string newCategoryName3,
            string creditCardNo, DateTime creditCardExpDate, string creditCardName, string creditCardPin, bool useBusinessAddress, string billingStreetAddress, string billingStreetAddress2,
            string billingCity, string billingState, string billingZip,
            string pictureContentType, byte[] picture,
            double? latitude, double? longitude)
        {
            return this.ZatifyEFDB.spAPI_Business_RegisterStep2(token.ToString(), description, referencedBy,
                 DateTime.Parse(businessHours.SunFrom.ToString()), DateTime.Parse(businessHours.SunTo.ToString()), businessHours.SunClosed,
                 DateTime.Parse(businessHours.MonFrom.ToString()), DateTime.Parse(businessHours.MonTo.ToString()), businessHours.MonClosed,
                 DateTime.Parse(businessHours.TueFrom.ToString()), DateTime.Parse(businessHours.TueTo.ToString()), businessHours.TueClosed,
                 DateTime.Parse(businessHours.WedFrom.ToString()), DateTime.Parse(businessHours.WedTo.ToString()), businessHours.WedClosed,
                 DateTime.Parse(businessHours.ThuFrom.ToString()), DateTime.Parse(businessHours.ThuTo.ToString()), businessHours.ThuClosed,
                 DateTime.Parse(businessHours.FriFrom.ToString()), DateTime.Parse(businessHours.FriTo.ToString()), businessHours.FriClosed,
                 DateTime.Parse(businessHours.SatFrom.ToString()), DateTime.Parse(businessHours.SatTo.ToString()), businessHours.SatClosed,
                categoriesIds, newCategoryName1, newCategoryName2, newCategoryName3, creditCardNo, creditCardExpDate, creditCardName, creditCardPin,
                useBusinessAddress, billingStreetAddress, billingStreetAddress2, billingCity, billingState, billingZip,
                pictureContentType, picture,
                latitude, longitude).FirstOrDefault().Value;
        }

        public spAPI_Promotion_Add_Result Business_AddPromotion(Guid token)
        {
            return this.ZatifyEFDB.spAPI_Promotion_Add(token.ToString()).FirstOrDefault();
        }

        public spAPI_PromotionCategory_Add_Result Business_AddPromotionCategories(Guid token, int promotionId, string categoriesIds)
        {
            return this.ZatifyEFDB.spAPI_PromotionCategory_Add(token.ToString(), promotionId, categoriesIds).FirstOrDefault();
        }

        #endregion

        #region Promotions

        public IQueryable<Promotion> PromotionsGetList(int businessId)
        {
            return ZatifyEFDB.Promotion_GetList(businessId).AsQueryable();
        }

        public IQueryable<Promotion> PromotionsGetByBusinessToken(Guid token)
        {
            return this.ZatifyEFDB.spAPI_Business_GetPromotions(token.ToString(), true).AsQueryable();
        }

        public Int32 PromotionDeleteByBusinessTokenAndId(Guid token, int promotionId)
        {
            return this.ZatifyEFDB.spAPI_Business_DeletePromotion(token.ToString(), promotionId).FirstOrDefault().Value;
        }

        public Promotion PromotionGetById(int id)
        {
            return ZatifyEFDB.Promotion_GetById(id).FirstOrDefault();
        }

        public Promotion PromotionGetByTokenAndId(Guid token, int promotionId)
        {
            return this.ZatifyEFDB.spAPI_Business_GetPromotionDetails(token.ToString(), promotionId, true).FirstOrDefault();
        }

        public IQueryable<Category> PromotionGetCategoriesByPromotionId(int promotionId)
        {
            return ZatifyEFDB.Promotion_GetCategoriesByPromotionId(promotionId).AsQueryable();
        }

        public IQueryable<Promotion> Deals(Guid token, double? latitude, double? longitude)
        {
            return this.ZatifyEFDB.spAPI_Business_GetDeals(token.ToString(), latitude, longitude, true).AsQueryable();
        }

        public Int32 Promotion_ProximityRadius_Update(Guid token, int promotionId, int proximityRadiusId, int? customRange,
            bool over200MilesFlag, bool registeredOutsideOfZip, bool registeredOutsideOfState, bool registeredOutsideOfCity)
        {
            return this.ZatifyEFDB.spAPI_Promotion_ProximityRadius_Update(token.ToString(), promotionId, proximityRadiusId, customRange,
                over200MilesFlag, registeredOutsideOfZip, registeredOutsideOfState, registeredOutsideOfCity).FirstOrDefault().Value;
        }

        public Int32 Promotion_BaseCostTiming_Update(Guid token, int promotionId, int baseCostTimingId, DateTime? baseCostTimingScheduledAt,
            DateTime? baseCostTimingStarts, DateTime? baseCostTimingEnds, DateTime? baseCostTimingStartsWithinDay, DateTime? baseCostTimingEndsWithinDay)
        {
            return this.ZatifyEFDB.spAPI_Promotion_BaseCostTiming_Update(token.ToString(), promotionId, baseCostTimingId, baseCostTimingScheduledAt,
                baseCostTimingStarts, baseCostTimingEnds, baseCostTimingStartsWithinDay, baseCostTimingEndsWithinDay).FirstOrDefault().Value;
        }

        public Int32 Promotion_BudgetAdd(Guid token, int promotionId, decimal summaPay, decimal summaRest, string promoName, string promoText, byte[] picture, string pictureContentType)
        {
            // 2 NULL PARAMS TEMP ++++++++++++++++++++++++++++++++++++++++\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
            return this.ZatifyEFDB.spAPI_Promotion_BudgetAdd(token.ToString(), promotionId, summaPay, summaRest /*amount*/, promoName, promoText, picture, pictureContentType).FirstOrDefault().Value;
        }

        public Int32 Promotion_Stop(Guid token, int promotionId)
        {
            return this.ZatifyEFDB.spAPI_Promotion_Stop(token.ToString(), promotionId).FirstOrDefault().Value;
        }

        public Int32 Promotion_Submit(Guid token, int promotionId, decimal summaPay, decimal summaRest)
        {
            // LAST 2 PARAMS TEMP ++++++++++++++++++++++++++++++++++++++++\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
            return this.ZatifyEFDB.spAPI_Promotion_Submit(token.ToString(), promotionId, summaPay, summaRest).FirstOrDefault().Value;
        }

        public Int32 Promotion_UpdateTiming(Guid token, int promotionId, int baseCostTimingId, DateTime? baseCostTimingScheduledAt,
            DateTime? baseCostTimingStarts, DateTime? baseCostTimingEnds, DateTime? baseCostTimingStartsWithinDay, DateTime? baseCostTimingEndsWithinDay)
        {
            return this.ZatifyEFDB.spAPI_Promotion_BaseCostTiming_Update(token.ToString(), promotionId, baseCostTimingId, baseCostTimingScheduledAt,
                baseCostTimingStarts, baseCostTimingEnds, baseCostTimingStartsWithinDay, baseCostTimingEndsWithinDay).FirstOrDefault().Value;
        }

        public Int32 Promotion_UpdateBudget(Guid token, int promotionId, decimal compaignBudget, string promotionName, string promotionText, byte[] picture, string pictureContentType, bool? singleUseOnly, string match)
        {
            return this.ZatifyEFDB.spAPI_Promotion_BudgetUpdate(token.ToString(), promotionId, compaignBudget, promotionName, promotionText, picture, pictureContentType, singleUseOnly, match)
                .FirstOrDefault().Value;
        }

        public spAPI_Promotion_GetPayInfo_Result Promotion_GetPayInfo_Result(Guid token, int promotionId)
        {
            return this.ZatifyEFDB.spAPI_Promotion_GetPayInfo(token.ToString(), promotionId).FirstOrDefault();
        }

        public string Promotion_Charge(string cardNumber, string cardPin, DateTime cardDateExpiration, decimal amount, string description)
        {
            string resultString = String.Empty;

            var uri = new Uri(String.Format("http://174.75.35.201/ZatifyAPI/Payment/Pay?cardNumber={0}&cardPin={1}&cardDateExpiration={2}&amount={3}&description={4}",
                cardNumber,
                cardPin,
                Uri.EscapeDataString(cardDateExpiration.ToString("yyyy-MM-dd HH':'mm':'ss")),
                amount,
                Uri.EscapeDataString(description)));

            var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri) as System.Net.HttpWebRequest;
            request.Method = "GET";

            try
            {
                using (var response = request.GetResponse())
                {
                    using (var stream = response.GetResponseStream())
                    {
                        resultString = new System.IO.StreamReader(stream).ReadToEnd();
                    }
                }
            }
            catch (Exception exc)
            {
                resultString = exc.Message;
            }

            return resultString;
        }

        #endregion

        #region US States

        public IQueryable<USState> USStates { get { return ZatifyEFDB.USState_GetList().AsQueryable(); } }

        #endregion

        #region REPORTS

        public List<Report_UserReferrer_Result> UserReferrerReport(DateTime? dateFrom, DateTime? dateTo, string referredByID, string referredID)
        {
            return ZatifyEFDB.Report_UserReferrer(
                dateFrom.HasValue ? dateFrom.Value : dateFrom,
                dateTo.HasValue ? dateTo.Value : dateTo,
                referredByID, referredID).ToList();
        }

        #endregion

        #region Billing

        public List<BillingTransactionHistory> BillingTransactionHistoryGet(Guid token, int? promotionId, DateTime? dateOperation)
        {
            return this.ZatifyEFDB.spAPI_Billing_Transaction_History(token.ToString(), promotionId, true, dateOperation).ToList();
        }

        public List<BillingTransactionHistoryForPromotion> BillingTransactionHistoryForPromotionGet(Guid token, int? promotionId, DateTime? dateOperation)
        {
            return this.ZatifyEFDB.spAPI_Billing_Transaction_GetPromotionTransaction(token.ToString(), promotionId, dateOperation, true).ToList();
        }

        //public spAPI_Billing_Transaction_GetCreditCardTransaction_Result BillingTransactionDetails_CreditCard(Guid token, int transactionId)
        //{
        //    return this.ZatifyEFDB.spAPI_Billing_Transaction_GetCreditCardTransaction(token.ToString(), transactionId, true).FirstOrDefault();
        //}

        //public spAPI_Billing_Transaction_GetPromotionTransaction_Result BillingTransactionDetails_DeditCard(Guid token, int promotionId, DateTime date)
        //{
        //    return null;//this.ZatifyEFDB.spAPI_Billing_Transaction_GetPromotionTransaction(token.ToString(), promotionId, date, true).FirstOrDefault();
        //}

        #endregion

        #region Contacting

        public sp_API_User_SendMessage_Result ContactUs_SendMessage(Guid token, string message)
        {
            return this.ZatifyEFDB.sp_API_User_SendMessage(token.ToString(), message).FirstOrDefault();
        }

        #endregion

        #region GeoLocation

        public List<GeoLocation> GeoLocation_GetList()
        {
            return this.ZatifyEFDB.spZipCode_GetAll().ToList();
        }

        public GeoLocation GeoLocation_GetByZipCode(string zipCode)
        {
            return this.ZatifyEFDB.spZipCode_GetByZipCode(zipCode).FirstOrDefault();
        }

        public GeoLocation Business_GetCoordinates(string streetAddress, string streetAddress2, string city, string state, string zip)
        {
            GeoLocation geoLoc = null;
            string resultString = String.Empty;

            var uri = new Uri(String.Format("http://174.75.35.201/ZatifyAPI/Business/GetCoo?streetAddress={0}&streetAddress2={1}&city={2}&state={3}&zip={4}",
                streetAddress,
                streetAddress2,
                city,
                state,
                zip));

            var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri) as System.Net.HttpWebRequest;
            request.Method = "GET";

            try
            {
                using (var response = request.GetResponse())
                {
                    using (var stream = response.GetResponseStream())
                    {
                        resultString = new System.IO.StreamReader(stream).ReadToEnd();
                    }
                }

                if (!String.IsNullOrWhiteSpace(resultString))
                    geoLoc = GetGeoLocationFromString(resultString);
                else
                    resultString = "Coordinates not founded";
            }
            catch (Exception exc)
            {
                resultString = exc.Message;
            }

            return geoLoc;
        }
        private GeoLocation GetGeoLocationFromString(string locationString)
        {
            var coordinatesArray = locationString.Split(';');

            var lat = Double.Parse(coordinatesArray[0]);//Latitude
            var lng = Double.Parse(coordinatesArray[1]);//Longitude

            return new GeoLocation() { Lat = lat, Long = lng };
        }


        #endregion
    }
}
